package beans;

import entities.AgeRating;
import entities.Categorie;
import entities.Comment;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import entities.JeuVideo;
import java.util.Collection;

@Stateless
public class VideoGameFacade extends AbstractFacade<JeuVideo> {

    @PersistenceContext(unitName = "ProjetAppliWebPU")
    private EntityManager em;

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    public VideoGameFacade() {
        super(JeuVideo.class);
    }

    public JeuVideo getByTitleAndCategory(String title, Categorie categorie) {
        Query query = em.createQuery("SELECT jv FROM JeuVideo jv WHERE jv.title = :title AND jv.categorie.name = :name");
        query.setParameter("title", title);
        query.setParameter("name", categorie.getName());

        try {
            return (JeuVideo) query.getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }

    public JeuVideo create(String title, Categorie categorie) {
        JeuVideo videoGame = getByTitleAndCategory(title, categorie);

        if (videoGame == null) {
            videoGame = new JeuVideo(title, categorie);
            create(videoGame);
            return videoGame;
        }

        return null;
    }

    public Collection<JeuVideo> getByCategory(Categorie category, int first, int max) {
        return getByCategory(category, first, max, "releaseDate", "DESC");
    }

    public Collection<JeuVideo> getByCategory(Categorie category, int first, int max, String sort, String value) {
        Query query = em.createQuery("SELECT jv FROM JeuVideo jv WHERE jv.categorie.id = :id ORDER BY jv." + sort + " " + value);
        query.setParameter("id", category.getId());
        query.setFirstResult(first);
        query.setMaxResults(max);
        return query.getResultList();
    }

    public Collection<JeuVideo> getByAgeRating(AgeRating ageRating, int first, int max, String sort, String value) {
        Query query = em.createQuery("SELECT jv FROM JeuVideo jv WHERE jv.ageRating.id = :id ORDER BY jv." + sort + " " + value);
        query.setParameter("id", ageRating.getId());
        query.setFirstResult(first);
        query.setMaxResults(max);
        return query.getResultList();
    }

    public int countByCategory(Categorie category) {
        Query query = em.createQuery("SELECT COUNT(jv) FROM JeuVideo jv WHERE jv.categorie.id = :id");
        query.setParameter("id", category.getId());
        return Integer.valueOf(query.getSingleResult().toString());
    }

    public int countByAgeRating(AgeRating ageRating) {
        Query query = em.createQuery("SELECT COUNT(jv) FROM JeuVideo jv WHERE jv.ageRating.id = :id");
        query.setParameter("id", ageRating.getId());
        return Integer.valueOf(query.getSingleResult().toString());
    }

    public Collection<JeuVideo> getLast(int max) {
        Query query = em.createQuery("SELECT jv FROM JeuVideo jv ORDER BY jv.releaseDate DESC");
        query.setMaxResults(max);
        return query.getResultList();
    }

    public Collection<JeuVideo> getSimilars(JeuVideo videoGame, int max) {
        Query query = em.createQuery("SELECT jv FROM JeuVideo jv WHERE jv.id <> :jv_id AND jv.categorie.id = :c_id ORDER BY jv.releaseDate DESC");
        query.setParameter("jv_id", videoGame.getId());
        query.setParameter("c_id", videoGame.getCategorie().getId());
        query.setMaxResults(max);
        return query.getResultList();
    }

    public Collection<JeuVideo> getAll() {
        Query query = em.createQuery("SELECT jv FROM JeuVideo jv ORDER BY jv.title, jv.categorie.name");
        return query.getResultList();
    }

    public Collection<JeuVideo> getByKeyword(String keyword) {
        Query query = em.createQuery("SELECT jv FROM JeuVideo jv WHERE LOWER(jv.title) LIKE :keyword ORDER BY jv.title");
        query.setParameter("keyword", "%" + keyword.toLowerCase() + "%");
        return query.getResultList();
    }

    public Collection<JeuVideo> getByCategoryKeyword(String keyword) {
        Query query = em.createQuery("SELECT jv FROM JeuVideo jv WHERE LOWER(jv.categorie.name) LIKE :keyword ORDER BY jv.title");
        query.setParameter("keyword", "%" + keyword.toLowerCase() + "%");
        return query.getResultList();
    }

    /**public Collection<JeuVideo> getByTagKeyword(String keyword) {
        Query q = em.createQuery("SELECT DISTINCT jv FROM JeuVideo jv, IN(jv.tags) t WHERE LOWER(t.nom) LIKE :keyword ORDER BY jv.title");
        q.setParameter("keyword", "%" + keyword.toLowerCase() + "%");
        return q.getResultList();
    }*/

    public Collection<Object> getByPublisherKeyword(String keyword, boolean all) {
        Query query;

        if (all) {
            query = em.createQuery("SELECT jv FROM JeuVideo jv WHERE LOWER(jv.publisher) LIKE :keyword ORDER BY jv.title");
        } else {
            query = em.createQuery("SELECT DISTINCT jv.publisher FROM JeuVideo jv WHERE LOWER(jv.publisher) LIKE :keyword ORDER BY jv.publisher");
        }

        query.setParameter("keyword", "%" + keyword.toLowerCase() + "%");
        return query.getResultList();
    }

    public Collection<String> getTitles() {
        Query q = em.createQuery("SELECT DISTINCT jv.title FROM JeuVideo jv ORDER BY jv.title");
        return q.getResultList();
    }

    public Collection<String> getPublishers() {
        Query q = em.createQuery("SELECT DISTINCT jv.publisher FROM JeuVideo jv ORDER BY jv.publisher");
        return q.getResultList();
    }

    public Collection<Comment> getComments(JeuVideo videoGames) {
        Query query = em.createQuery("SELECT c FROM JeuVideo jv, IN(jv.commentaires) c WHERE jv.id = :id ORDER BY c.date DESC");
        query.setParameter("id", videoGames.getId());
        return query.getResultList();
    }

    public void addComment(Comment comment, JeuVideo videoGame) {
        videoGame.getCommentaires().add(comment);
        edit(videoGame);
    }

    public int getAverageNote(JeuVideo videoGame) {
        Collection<Comment> comments = videoGame.getCommentaires();

        if (comments.isEmpty()) {
            return 0;
        }

        int sum = 0;

        for (Comment comment : comments) {
            sum += comment.getNote().getNote();
        }

        int average = sum / comments.size();
        return average;
    }
}
